package com.ilibrary.service.impl;

import java.lang.reflect.InvocationTargetException;
import java.util.HashMap;
import java.util.List;

import org.apache.commons.beanutils.BeanUtils;

import com.ilibrary.base.MyBaseVO;
import com.ilibrary.constants.MyConstants;
import com.ilibrary.constants.MyMsgConstants;
import com.ilibrary.db.dao.hibernate.BookDao;
import com.ilibrary.db.dao.hibernate.BorrowDao;
import com.ilibrary.db.dao.hibernate.CategoryDao;
import com.ilibrary.db.dao.hibernate.UserInfoDao;
import com.ilibrary.db.entity.Book;
import com.ilibrary.db.entity.Borrow;
import com.ilibrary.db.entity.Category;
import com.ilibrary.db.entity.UserInfo;
import com.ilibrary.service.BorrowService;
import com.ilibrary.utils.MyColumnIndicator;
import com.ilibrary.web.dto.ResultDto;
import com.ilibrary.web.vo.BorrowVO;
import com.sun.org.apache.xml.internal.serializer.utils.Utils;

public class BorrowServiceImpl implements BorrowService {
	
	private BorrowDao borrowDao;
	private CategoryDao categoryDao;
	private BookDao bookDao;
	private UserInfoDao userInfoDao;

	public BorrowDao getBorrowDao() {
		return borrowDao;
	}
	public void setBorrowDao(BorrowDao borrowDao) {
		this.borrowDao = borrowDao;
	}
	public CategoryDao getCategoryDao() {
		return categoryDao;
	}
	public void setCategoryDao(CategoryDao categoryDao) {
		this.categoryDao = categoryDao;
	}
	public BookDao getBookDao() {
		return bookDao;
	}
	public void setBookDao(BookDao bookDao) {
		this.bookDao = bookDao;
	}
	public UserInfoDao getUserInfoDao() {
		return userInfoDao;
	}
	public void setUserInfoDao(UserInfoDao userInfoDao) {
		this.userInfoDao = userInfoDao;
	}
	
	@Override
	public ResultDto<MyBaseVO> add(BorrowVO borrowVO) {
		
		ResultDto<MyBaseVO> resultDto = new ResultDto<MyBaseVO>();
		
		UserInfo userInfo = userInfoDao.findById(borrowVO.getUserId());
		Book book = bookDao.findById(borrowVO.getBookId());
		
		if(userInfo == null) {
			resultDto.setSuccess(false);
			resultDto.setMsg(MyMsgConstants.USER_NOT_EXIST);
			return resultDto;
		}
		
		if(book == null) {
			resultDto.setSuccess(false);
			resultDto.setMsg(MyMsgConstants.BOOK_NOT_EXIST);
			return resultDto;
		}
		
		if(book.getBookStatus() == MyColumnIndicator.BOOK_STATUS_BE_LOAN) {
			resultDto.setSuccess(false);
			resultDto.setMsg(MyMsgConstants.BOOK_CAN_NOT_LOAN);
			return resultDto;
		}

		HashMap<String, Object> hashMap = new HashMap<String, Object>();
		hashMap.put("userInfo", userInfo);
		hashMap.put("borrowStatus", MyColumnIndicator.BORROW_STATUS_NEW);
		int userLoanCnt = borrowDao.findByExample(hashMap).size();
		if(userLoanCnt >= MyConstants.USER_LOAN_BOOK_CNT_MAX) {
			resultDto.setSuccess(false);
			resultDto.setMsg(MyMsgConstants.USER_LOAN_CNT_REACH_MAX);
			return resultDto;
		}
		
		Borrow borrow = new Borrow();
		try {
			BeanUtils.copyProperties(borrow, borrowVO);
			borrow.setBook(book);
			borrow.setUserInfo(userInfo);
			borrowDao.add(borrow);
			book.setBookStatus(MyColumnIndicator.BOOK_STATUS_BE_LOAN);
			bookDao.update(book);
		} catch (IllegalAccessException e) {
			resultDto.setSuccess(false);
			resultDto.setMsg(MyMsgConstants.ADD_EXCEPTION);
			e.printStackTrace();
			return resultDto;
		} catch (InvocationTargetException e) {
			resultDto.setSuccess(false);
			resultDto.setMsg(MyMsgConstants.ADD_EXCEPTION);
			e.printStackTrace();
			return resultDto;
		}
		resultDto.setSuccess(true);
		return resultDto;
	}
	
	@Override
	public ResultDto<BorrowVO> findByBookId(String bookId) {
		ResultDto<BorrowVO> resultDto = new ResultDto<BorrowVO>();
		BorrowVO borrowVO = new BorrowVO();
		HashMap<String, Object> hashMap = new HashMap<String, Object>();
		Book book = bookDao.findById(Integer.parseInt(bookId));
		if(book == null) {
			resultDto.setSuccess(false);
			resultDto.setMsg(MyMsgConstants.BOOK_NOT_EXIST);
			return resultDto;
		}
		
		hashMap.put("book", book);
		hashMap.put("borrowStatus", MyColumnIndicator.BORROW_STATUS_NEW);
		List<Borrow> borrowVOList = borrowDao.findByExample(hashMap);
		if(borrowVOList.size() == 0) {
			resultDto.setSuccess(false);
			resultDto.setMsg(MyMsgConstants.BORROW_NOT_EXIST);
			return resultDto;
		}
		Borrow borrow = borrowVOList.get(0);
		
		try {
			BeanUtils.copyProperties(borrowVO, borrow);
			borrowVO.setBookId(borrow.getBook().getBookId());
			borrowVO.setUserId(borrow.getUserInfo().getUserId());
		} catch (IllegalAccessException e) {
			resultDto.setSuccess(false);
			resultDto.setMsg(MyMsgConstants.QUERY_EXCEPTION);
			e.printStackTrace();
			return resultDto;
		} catch (InvocationTargetException e) {
			resultDto.setSuccess(false);
			resultDto.setMsg(MyMsgConstants.QUERY_EXCEPTION);
			e.printStackTrace();
			return resultDto;
		}
		resultDto.addToResultList(borrowVO);
		resultDto.setSuccess(true);
		return resultDto;
	}
	
	@Override
	public ResultDto<MyBaseVO> update(BorrowVO borrowVO) {
		ResultDto<MyBaseVO> resultDto = new ResultDto<MyBaseVO>();
		Borrow borrow = new Borrow();
		Book book = bookDao.findById(borrowVO.getBookId());
		UserInfo userInfo = userInfoDao.findById(borrowVO.getUserId());
		try {
			BeanUtils.copyProperties(borrow, borrowVO);
			borrow.setBook(bookDao.findById(borrowVO.getBookId()));
			borrow.setUserInfo(userInfoDao.findById(borrowVO.getUserId()));
		} catch (IllegalAccessException e) {
			e.printStackTrace();
		} catch (InvocationTargetException e) {
			e.printStackTrace();
		}
		borrow.setBook(book);
		borrow.setUserInfo(userInfo);
		borrowDao.update(borrow);
		resultDto.setSuccess(true);
		return resultDto;
	}
	@Override
	public ResultDto<BorrowVO> findByUserIdAndStatus(String userId, Integer borrowStatus) {
		ResultDto<BorrowVO> resultDto = new ResultDto<BorrowVO>();
		HashMap<String, Object> map = new HashMap<String, Object>();
		UserInfo userInfo = userInfoDao.findById(userId);
		map.put("userInfo", userInfo);
		map.put("borrowStatus", borrowStatus);
		List<Borrow> borrowList = borrowDao.findByExample(map);
		BorrowVO borrowVO = null;
		Book book = null;
		Category category = null;
		for (Borrow borrow : borrowList) {
			borrowVO = new BorrowVO();
			try {
				BeanUtils.copyProperties(borrowVO, borrow);
			} catch (Exception e) {
				e.printStackTrace();
			}
			book = bookDao.findById(borrow.getBook().getBookId());
			category = categoryDao.findById(book.getCategory().getCategoryId());
			if(borrow.getBorrowStatus() == MyColumnIndicator.BORROW_STATUS_NEW) {
				borrowVO.setBorrowStatusString(MyColumnIndicator.BORROW_STATUS_NEW_STRING);
			}else {
				borrowVO.setBorrowStatusString(MyColumnIndicator.BORROW_STATUS_COMPLETE_STRING);
			}
			borrowVO.setBookId(book.getBookId());
			borrowVO.setBookName(book.getBookName());
			borrowVO.setBookAuthor(book.getBookAuthor());
			borrowVO.setBookPrice(book.getBookPrice());
			borrowVO.setBookPubHouse(book.getBookPubHouse());
			borrowVO.setBookPubDt(book.getBookPubDt());
			borrowVO.setCategoryName(category.getCategoryName());
			resultDto.addToResultList(borrowVO);
		}
		return resultDto;
	}
	
	@Override
	public BorrowVO findById(int borrowId) {
		Borrow borrow = borrowDao.findById(borrowId);
		BorrowVO borrowVO = new BorrowVO();
		try {
			borrowVO.setBorrowId(borrow.getBorrowId());
			borrowVO.setBorrowStatus(borrow.getBorrowStatus());
			borrowVO.setBorrowRenewNum(borrow.getBorrowRenewNum());
			borrowVO.setBorrowDt(borrow.getBorrowDt());
			borrowVO.setBorrowDeadline(borrow.getBorrowDeadline());
			borrowVO.setBookId(borrow.getBook().getBookId());
			borrowVO.setUserId(borrow.getUserInfo().getUserId());
			borrowVO.setCreateDt(borrow.getCreateDt());
			borrowVO.setCreateUser(borrow.getCreateUser());
			borrowVO.setUpdateDt(borrow.getUpdateDt());
			borrowVO.setUpdateUser(borrow.getUpdateUser());
		} catch (Exception e) {
			e.printStackTrace();
		} 
		return borrowVO;
	}
	
}
